#ifdef _COMP
#define __COMP '_COMP'
#else
#define __COMP TMF
#endif
#ifdef TMF_PATH
#define __TMF_PATH TMF_PATH
#endif

#define FUNC(funcname) __COMP##_fnc_##funcname
#define EFUNC(funcname) edt_fnc_##funcname
#define TFUNC(funcname) tyr_fnc_##funcname
#define FFUNC(funcname) tmf_fnc_##funcname
#define GVAR(varname) __COMP##_##varname
#define QUOTE(qtext) #qtext
#define QGVAR(varname) QUOTE(GVAR(varname))
#define MPATH(pathname) __TMF_PATH##\##pathname
#define QPATH(pathname) QUOTE(MPATH(pathname))

#define PARAMS_1(param1) if (count _this > 0) then { param1 = _this select 0 }
#define PARAMS_2(param1,param2) PARAMS_1(param1); if (count _this > 1) then { param2 = _this select 1 }
#define PARAMS_3(param1,param2,param3) PARAMS_2(param1,param2); if (count _this > 2) then { param3 = _this select 2 }
#define PARAMS_4(param1,param2,param3,param4) PARAMS_3(param1,param2,param3); if (count _this > 3) then { param4 = _this select 3 }
#define PARAMS_5(param1,param2,param3,param4,param5) PARAMS_4(param1,param2,param3,param4); if (count _this > 4) then { param5 = _this select 4 }
#define PARAMS_6(param1,param2,param3,param4,param5,param6) PARAMS_5(param1,param2,param3,param4,param5); if (count _this > 5) then { param6 = _this select 5 }
#define PARAMS_7(param1,param2,param3,param4,param5,param6,param7) PARAMS_6(param1,param2,param3,param4,param5,param6); if (count _this > 6) then { param7 = _this select 6 }
#define PARAMS_8(param1,param2,param3,param4,param5,param6,param7,param8) PARAMS_7(param1,param2,param3,param4,param5,param6,param7); if (count _this > 7) then { param8 = _this select 7 }

#define ARR_0 []
#define ARR_1(v1) [v1]
#define ARR_2(v1,v2) [v1,v2]
#define ARR_3(v1,v2,v3) [v1,v2,v3]
#define ARR_4(v1,v2,v3,v4) [v1,v2,v3,v4]
#define ARR_5(v1,v2,v3,v4,v5) [v1,v2,v3,v4,v5]
#define ARR_6(v1,v2,v3,v4,v5,v6) [v1,v2,v3,v4,v5,v6]
#define ARR_7(v1,v2,v3,v4,v5,v6,v7) [v1,v2,v3,v4,v5,v6,v7]
#define ARR_8(v1,v2,v3,v4,v5,v6,v7,v8) [v1,v2,v3,v4,v5,v6,v7,v8]
#define ARR_9(v1,v2,v3,v4,v5,v6,v7,v8,v9) [v1,v2,v3,v4,v5,v6,v7,v8,v9]
#define ARR_10(v1,v2,v3,v4,v5,v6,v7,v8,v9,v10) [v1,v2,v3,v4,v5,v6,v7,v8,v9,v10]



#define EXECNOW(xfile1) call compile preprocessFileLineNumbers xfile1
#define COMPILETO(xdfunc,xpath2,xfile2) xdfunc = compile preprocessFileLineNumbers format["%1%2",xpath2,xfile2]
#define COMPILEFINAL(xdfunc,xpath2,xfile2) xdfunc = compileFinal preprocessFileLineNumbers format["%1%2",xpath2,xfile2]

#define TRANSLATE(xtranslate) (xtranslate call FFUNC(translate))
#define NEXTJIPID (call FFUNC(nextJipID))

#define CHK_ARRAY(xvar1,xdefault1) if (isnil QUOTE(xvar1)) then {xvar1 = xdefault1;} else { if (typename xvar1 != typename []) then { xvar1 = xdefault1; } }
#define CHK_STRING(xvar2,xdefault2) if (isnil QUOTE(xvar2)) then {xvar2 = xdefault2;} else { if (typename xvar2 != typename "") then { xvar2 = xdefault2; } }
#define CHK_OBJECT(xvar3,xdefault3) if (isnil QUOTE(xvar3)) then {xvar3 = xdefault3;} else { if (typename xvar3 != typename objNull) then { xvar3 = xdefault3; } }
#define CHK_GROUP(xvar4,xdefault4) if (isnil QUOTE(xvar4)) then {xvar4 = xdefault4;} else { if (typename xvar4 != typename grpNull) then { xvar4 = xdefault4; } }
#define CHK_SCALAR(xvar5,xdefault5) if (isnil QUOTE(xvar5)) then {xvar5 = xdefault5;} else { if (typename xvar5 != typename 0) then { xvar5 = xdefault5; } }
#define CHK_BOOL(xvar6,xdefault6) if (isnil QUOTE(xvar6)) then {xvar6 = xdefault6;} else { if (typename xvar6 != typename true) then { xvar6 = xdefault6; } }

#define CHK_NIL(xvar15,xdefault15) (if (isnil QUOTE(xvar15)) then {xdefault15} else {xvar15})

#define AND_ALSO(cond1,cond2) (if ((cond1)) then {(cond2)} else {false})
#define OR_ELSE(cond3,cond4) (if ((cond3)) then {true} else {(cond4)})

#define IS_ARRAY(xvar7) (typename xvar7 == typename [])
#define IS_STRING(xvar8) (typename xvar8 == typename "")
#define IS_OBJECT(xvar9) (typename xvar9 == typename objNull)
#define IS_GROUP(xvar10) (typename xvar10 == typename grpNull)
#define IS_SCALAR(xvar11) (typename xvar11 == typename 0)
#define IS_BOOL(xvar12) (typename xvar12 == typename true)
#define IS_MARKER(xvar13) ((markerShape xvar13) != "")
#define IS_SIDE(xvar14) (typename xvar14 == typename west)
#define IS_TRIGGER(xvar15) ((typeof xvar15) == "EmptyDetector")
#define IS_CONFIG(conf1) ((typeName conf1) == (typeName configFile))

#define IS_EAST (GVAR(own_side) == "EAST")
#define IS_WEST (GVAR(own_side) == "WEST")

#define GETVAL(array,index,default) (if (count array > index) then { (if(isnil{array select index}) then {default} else { array select index }) } else { default })
#define SETVAL(array,index,value) (if (index < 0) then { array set [count array,  value] } else { array set [index, value] })

#define DEFAULT_PARAM(param,index,default) param = GETVAL(_this, index, default)

#define MNGETVAR(mvarname,jdefault) (if (isnil {missionNamespace getVariable mvarname}) then { jdefault } else { missionNamespace getVariable mvarname })
#define MNSETVAR(mvarname,mval) missionNamespace setVariable [mvarname, mval]
#define MNSETVARP(mvarname,mval) missionNamespace setVariable [mvarname, mval, true]
#define PGETVAR(pvarname,pdefault) (if (isnil {player getVariable pvarname}) then { pdefault } else { player getVariable pvarname })
#define PSETVAR(pvarname,pval) player setVariable [pvarname, pval]
#define PSETVARP(pvarname,pval) player setVariable [pvarname, pval, true]
#define OGETVAR(object,ovarname,odefault) (if (isnil {object getVariable ovarname}) then { odefault } else { object getVariable ovarname })
#define OSETVAR(object,ovarname,oval) object setVariable [ovarname, oval]
#define OSETVARP(object,ovarname,oval) object setVariable [ovarname, oval, true]
#define JIPGETVAR(jvarname,jdefault) (if (isnil {JIPH getVariable jvarname}) then { jdefault } else { JIPH getVariable jvarname })
#define JIPSETVAR(jvarname,jval) JIPH setVariable [jvarname, jval, true]
#define JIPSETVARP(jvarname,jval) JIPH setVariable [jvarname, jval, true]
#define UIGETVAR(uvarname, udefault) (if (isnil {uiNamespace getVariable uvarname}) then { udefault } else { uiNamespace getVariable uvarname })

#define addDead(xunitx) GVAR(allunits_dead) set [count GVAR(allunits_dead), xunitx]
#define addDeadObjective(xunitx) GVAR(allunits_objective_dead) set [count GVAR(allunits_objective_dead), xunitx]
#define posNdir(xposNdir) if (typename xposNdir == typename []) then { \
		if (count xposNdir == 3) then { \
			_pos = xposNdir; \
			_dir = 0; \
		} else { \
			if (count xposNdir > 1) then { \
				_dir = xposNdir select 1; \
				_pos = xposNdir select 0; \
			} else { \
				_pos = xposNdir; \
				_dir = 0; \
			}; \
		}; \
	} else { \
		_pos = [0,0,0]; \
		_dir = 0; \
	}
#define posNradius(xposNradius,defaultradius) if (typename xposNradius == typename []) then { \
		if (count xposNradius == 3) then { \
			_pos = xposNradius; \
			_radius = defaultradius; \
		} else { \
			if (count xposNradius > 1) then { \
				_radius = xposNradius select 1; \
				_pos = xposNradius select 0; \
			} else { \
				_pos = xposNradius; \
				_radius = defaultradius; \
			}; \
		}; \
	} else { \
		_pos = [0,0,0]; \
		_radius = 0; \
	}

#define ADD(vari,incv) vari = vari + incv
#define SUB(vard,decv) vard = vard - decv
#define INC(vari) vari = vari + 1
#define DEC(vard) vard = vard - 1

#define MPCHECK if (IsMultiplayer) then { \
	if ((call FFUNC(PlayersNumber)) == 0) then { \
		if (!GVAR(all_simulation_stopped)) then { \
			GVAR(all_simulation_stopped) = true; \
			{_x enableSimulation false} forEach allUnits; \
		}; \
	}; \
	waitUntil {sleep (1.012 + random 1);(call FFUNC(PlayersNumber)) > 0}; \
	if (GVAR(all_simulation_stopped)) then { \
		{_x enableSimulation true} forEach allUnits; \
		GVAR(all_simulation_stopped) = false; \
	}; \
}

#define TMFPROFILERSTART
#define TMFPROFILERSTOP

#ifdef THIS_FILE
#define THIS_FILE_ THIS_FILE
#else
#define THIS_FILE_ __FILE__
#endif

#ifdef __FORCE_TRACE__
#undef __FORCE_DEBUG__
#define __FORCE_DEBUG__
#endif

#ifdef __FORCE_DEBUG__
#undef __FORCE_INFO__
#define __FORCE_INFO__
#endif

#define INIT_DEBUG(lvl) if (isnil "diag_debug_level") then { diag_debug_level = lvl };

#define IS_LOG (diag_debug_level >= 0)
#define IS_INFO (isServer && diag_debug_level > 0) || (!isServer && diag_debug_level > 5)
#define IS_DEBUG (isServer && diag_debug_level > 1) || (!isServer && diag_debug_level > 6)
#define IS_TRACE (isServer && diag_debug_level > 2) || (!isServer && diag_debug_level > 7)

#ifdef __FORCE_INFO__
#define INFO(MESSAGE) diag_log format ["%1|INFO|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE]
#define INFO_1(MESSAGE,A) diag_log format ["%1|INFO|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A]
#define INFO_2(MESSAGE,A,B) diag_log format ["%1|INFO|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B]
#else
#define INFO(MESSAGE) if (IS_INFO) then { diag_log format ["%1|INFO|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE] }
#define INFO_1(MESSAGE,A) if (IS_INFO) then { diag_log format ["%1|INFO|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A] }
#define INFO_2(MESSAGE,A,B) if (IS_INFO) then { diag_log format ["%1|INFO|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B] }
#endif

#ifdef __FORCE_DEBUG__
#define DEBUG(MESSAGE) diag_log format ["%1|DEBUG|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE]
#define DEBUG_1(MESSAGE,A) diag_log format ["%1|DEBUG|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A]
#define DEBUG_2(MESSAGE,A,B) diag_log format ["%1|DEBUG|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B]
#else
#define DEBUG(MESSAGE) if (IS_DEBUG) then { diag_log format ["%1|DEBUG|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE] }
#define DEBUG_1(MESSAGE,A) if (IS_DEBUG) then { diag_log format ["%1|DEBUG|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A] }
#define DEBUG_2(MESSAGE,A,B) if (IS_DEBUG) then { diag_log format ["%1|DEBUG|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B] }
#endif

#ifdef __FORCE_TRACE__
#define TRACE(MESSAGE) diag_log format ["%1|TRACE|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE]
#define TRACE_1(MESSAGE,A) diag_log format ["%1|TRACE|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A]
#define TRACE_2(MESSAGE,A,B) diag_log format ["%1|TRACE|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B]
#else
#define TRACE(MESSAGE) if (IS_TRACE) then { diag_log format ["%1|TRACE|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE] }
#define TRACE_1(MESSAGE,A) if (IS_TRACE) then { diag_log format ["%1|TRACE|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A] }
#define TRACE_2(MESSAGE,A,B) if (IS_TRACE) then { diag_log format ["%1|TRACE|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B] }
#endif

#define TLOG(MESSAGE) if (IS_LOG) then { diag_log format ["%1|LOG|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE] }
#define TLOG_1(MESSAGE,A) if (IS_LOG) then { diag_log format ["%1|LOG|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A] }
#define TLOG_2(MESSAGE,A,B) if (IS_LOG) then { diag_log format ["%1|LOG|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B] }

#define ERROR(MESSAGE) diag_log format ["%1|ERROR|%2|%3|%4|%5|%6",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE]
#define ERROR_1(MESSAGE,A) diag_log format ["%1|ERROR|%2|%3|%4|%5|%6;%7",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A]
#define ERROR_2(MESSAGE,A,B) diag_log format ["%1|ERROR|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,MESSAGE,A,B]

#define NETLOG(MESSAGE) if (!isnil QUOTE(FFUNC(callEvent))) then { [QGVAR(s_log),ARR_9("%1|REMOTE|%2|%3|%4|%5|%6;%7;%8",QUOTE(__COMP), time, diag_frameno, THIS_FILE_,__LINE__,getPlayerUID player,name player,MESSAGE)] call FFUNC(callEvent) }

#define WAITINIT(filename)	waituntil {GVAR(initialized)}; \
		TRACE_1(QUOTE(filename),_this)
	
